package cn.yeziji.forum.filter;

import cn.yeziji.forum.common.FilterToken;
import cn.yeziji.forum.common.key.UserCacheKey;
import cn.yeziji.forum.utils.CacheUtils;
import cn.yeziji.forum.utils.SpringUtils;
import cn.yeziji.forum.utils.UserOnlineUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 拦截判断是否刷新 token
 *
 * @author gzkemays
 * @since 2022/9/5 15:07
 */
@Component
@Slf4j
public class TokenRefreshFilter implements HandlerInterceptor {
  CacheUtils cache = SpringUtils.getBean(CacheUtils.class);

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    String token = request.getHeader(HttpHeaders.AUTHORIZATION);
    if (StringUtils.isNotBlank(token)) {
      UserOnlineUtils.setToken(token);
    }
    log.info("{} 访问 ---> {}", UserOnlineUtils.getUserName(), request.getRequestURI());
    return HandlerInterceptor.super.preHandle(request, response, handler);
  }

  @Override
  public void postHandle(
      HttpServletRequest request,
      HttpServletResponse response,
      Object handler,
      ModelAndView modelAndView)
      throws Exception {
    HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
  }

  @Override
  public void afterCompletion(
      HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      throws Exception {
    log.info("访问 ---> {} -- 结束", request.getRequestURI());
    String token = request.getHeader(HttpHeaders.AUTHORIZATION);
    // 获取用户权限以及刷新 token
    FilterToken authentication = getAuthentication(token);
    if (authentication != null) {
      String refreshToken = authentication.getRefreshToken();
      // 如果刷新了 token 那么将 token 塞入响应头当中
      if (StringUtils.isNotBlank(refreshToken)) {
        log.info("访问 ---> {} -- 刷新 token", request.getRequestURI());
        response.setHeader(HttpHeaders.AUTHORIZATION, refreshToken);
      }
    }
    UserOnlineUtils.clear();
    HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
  }

  private FilterToken getAuthentication(String token) {
    if (Objects.nonNull(token)) {
      FilterToken filterToken = new FilterToken();
      String refreshToken;
      // 判断是否生成了 refresh token
      if ((refreshToken = cache.get(UserCacheKey.GENERATE.getRefreshTokenKey(token))) != null) {
        filterToken.setRefreshToken(refreshToken);
      }
      return filterToken;
    }
    return null;
  }
}
